package com.financing.wap.web.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import com.financing.wap.common.ResultMap;
import com.financing.wap.common.ResultMap.STATUS;
import com.financing.wap.common.Session;
import com.financing.wap.common.SessionImpl;
import com.financing.wap.dto.DstMemberInfoDTO;
import com.financing.wap.service.IDstMemberInfoService;
import com.financing.wap.util.Constants;
import com.financing.wap.util.PropertiesUtils;
import com.financing.wap.util.SecureUtil;

/**
 * 登陆权限过滤Filter
 * @author localadmin
 *
 */
@Component(value="loginFilter")
public class LoginFilter implements Filter,ApplicationContextAware {

	private String encoding = "utf-8";
	
	protected final Logger log = LoggerFactory.getLogger(LoginFilter.class);
	
	private static String CONTEXT_PATH = "";
	
	@Autowired
	protected IDstMemberInfoService dstMemberInfoService;
		
	private static final String[] LINKS_REGEX = {
				"^*.*"
//				".*?/api/dstUserInfoExpand/.*?"
	};
	
	//会员收费接口过滤
	private static final String[] MEMBER_LINKS_REGEX = {
		".*?/api/dstUserVisitLog/listDstUserVisitLog",
		".*?/api/dstUserVisitLog/listDstUserVisitLogShare",
		".*?/api/dstUserVisitLog/queryNaturalWeek"
	};
	
	@Override
	public void destroy() {
		log.debug("destroy login filter");
		
	}
	
    /**
     * Default constructor. 
     */
    public LoginFilter() {
    }

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filterChain) throws IOException, ServletException {
		

		HttpServletRequest httpRequest =  (HttpServletRequest)request;
		HttpServletResponse httpResponse = (HttpServletResponse)response;
		
		httpRequest.setCharacterEncoding(encoding);
		httpResponse.setCharacterEncoding(encoding);

		String requestUri = httpRequest.getRequestURI();
		
		httpResponse.setHeader("Access-Control-Allow-Origin", PropertiesUtils.getValue("Access_Control_Allow_Origin"));
		httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
		httpResponse.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
		httpResponse.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,Authorization");
		httpResponse.setHeader("P3P","CP='IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT CAO PSA OUR'");
		httpResponse.setHeader("Content-Type","application/json;charset=UTF-8");
//		httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
//		System.out.println("=====================>:"+httpRequest.getSession().getId());
		
		//不走
		StringBuffer reqUrl = httpRequest.getRequestURL();
		if(reqUrl.toString().contains("qmxjj.iask.in")){
			filterChain.doFilter(request, response);
			return;
		}
		
		//微信接口
		if(requestUri.contains("wxapi")||requestUri.contains("/weixin/")){
			filterChain.doFilter(request, response);
			return;
		}
		
		//后台  session处理
		if(requestUri.contains("adminapi")){
			String actionName = requestUri.substring(requestUri.lastIndexOf("/")+1);
			if("queryLoginStatus.shtml".equals(actionName)||"login.shtml".equals(actionName)){
				filterChain.doFilter(request, response);
				return ;
			}
			Session session = (Session)httpRequest.getSession(true).getAttribute(Session.KEY_NAME);
			
			if(session == null || session.getLogin() == false){
				log.info("Not login ,plase login frist.....");
				//记录登陆前的URL
				preRequestRember(httpRequest);
				
				ResultMap result = new ResultMap();
				result.setStatus(STATUS.NEED_LOGIN);
				result.setStatusCode(ResultMap.STATUS_CODE_ONLOGIN);
				result.setMessage("Need login");
				result.setAttribute(Constants.ResultMessage,"未登录,请先登录");
				PrintWriter pw = response.getWriter();
				pw.write(JSONObject.fromObject(result).toString());
				return;
			}
		}else{
			log.info("login filter neetd login ");
			String token="";
			//前端其他接口 全部走token判断
			Cookie[] cookies = httpRequest.getCookies();
			if(cookies != null){
				try {
					for(Cookie tokenCookie : cookies ){
						log.debug("!tokenCookie name"+tokenCookie.getName());
						if(Constants._TOKEN.equals(tokenCookie.getName())){
							tokenCookie.setMaxAge(60*60*24);
							tokenCookie.setPath("/");
							httpResponse.addCookie(tokenCookie);
							token = tokenCookie.getValue();
							int k = 4-(token.length()%4);
							if(k!=4){
								for(int i = 0;i< k;i++){
									token = token +"=";
								}
							}
							break;
						}
					}
					token = SecureUtil.decrypt(token);
				} catch (Exception e) {
					log.info("parse token error.....",e);
				}
			}
			String openid=request.getParameter("openid");
			
			//所有接口都需要判断   注释
			if(needLogin(requestUri)){
				log.info("token:"+token+"==openid:"+openid);
				if(StringUtils.isBlank(token)||(StringUtils.isNotBlank(openid)&&!token.equals(openid))){
					ResultMap result = new ResultMap();
					result.setStatus(STATUS.NEED_LOGIN);
					result.setStatusCode(ResultMap.STATUS_CODE_ONLOGIN);
					result.setMessage("Need login");
					result.setAttribute(Constants.ResultMessage,"未登录,请先登录");
					PrintWriter pw = response.getWriter();
					pw.write(JSONObject.fromObject(result).toString());
					return;
				}
			}
			
			log.info("query member token :"+token);
			//会员权限过滤
			if(!needMember(requestUri)){
				filterChain.doFilter(request, response);
				return;
			}
			
			if(StringUtils.isBlank(token)||StringUtils.isBlank(openid)||!token.equals(openid)){
				ResultMap result = new ResultMap();
				result.setStatus(STATUS.NEED_LOGIN);
				result.setStatusCode(ResultMap.STATUS_CODE_ONLOGIN);
				result.setMessage("Need login");
				result.setAttribute(Constants.ResultMessage,"未登录,请先登录");
				PrintWriter pw = response.getWriter();
				pw.write(JSONObject.fromObject(result).toString());
				return;
			}
			
			log.info("query is  member :"+token);
			DstMemberInfoDTO dstMemberInfo=new DstMemberInfoDTO();
			dstMemberInfo.setUserOpenid(token);
			try {
				DstMemberInfoDTO dto = dstMemberInfoService.queryListGetFirst(dstMemberInfo);
				if(dto.getId()==null||dto.getMemberEndDate()==null||new Date().after(dto.getMemberEndDate())){
					ResultMap result = new ResultMap();
					result.setStatus(STATUS.NEED_MEMBEER);
					result.setStatusCode(ResultMap.STATUS_CODE_ONMEMBER);
					result.setMessage("Need member");
					result.setAttribute(Constants.ResultMessage,"未开通会员没有权限");
					PrintWriter pw = response.getWriter();
					pw.write(JSONObject.fromObject(result).toString());
					return;
				}
			} catch (SQLException e) {
				log.error("query member info :",e);
				ResultMap result = new ResultMap();
				result.setStatus(STATUS.NEED_MEMBEER);
				result.setStatusCode(ResultMap.STATUS_CODE_ONMEMBER);
				result.setMessage("Need member");
				result.setAttribute(Constants.ResultMessage,"未开通会员没有权限");
				PrintWriter pw = response.getWriter();
				pw.write(JSONObject.fromObject(result).toString());
				return;
			}
			
			filterChain.doFilter(request, response);
			return;
		}
		filterChain.doFilter(request, response);
	}
	
	/**
	 * 判断当前请求是否需要会员
	 * @param requestUri
	 */
	private boolean needMember(String requestUri){
		
		if(StringUtils.isEmpty(requestUri) || requestUri.equals(CONTEXT_PATH)){
			return false;
		}else{
			requestUri = requestUri.replaceFirst(CONTEXT_PATH, "");
		}
		/**
		 *排除根目录 
		 */
		if(requestUri.equals("/")){
			return false;
		}
		/**
		 * 排除满足正则的URL
		 */
		for(int i=0; i < MEMBER_LINKS_REGEX.length; i++){
			String regex = MEMBER_LINKS_REGEX[i];
			if(requestUri.matches(regex)){
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * 判断当前请求是否需要登陆
	 * @param requestUri
	 */
	private boolean needLogin(String requestUri){
		
		if(StringUtils.isEmpty(requestUri) || requestUri.equals(CONTEXT_PATH)){
			return false;
		}else{
			requestUri = requestUri.replaceFirst(CONTEXT_PATH, "");
		}
		
		/**
		 *排除根目录 
		 */
		if(requestUri.equals("/")){
			return false;
		}
		
		/**
		 * 排除满足正则的URL
		 */
		for(int i=0; i < LINKS_REGEX.length; i++){
			String regex = LINKS_REGEX[i];
			if(requestUri.matches(regex)){
				return false;
			}
		}
		
		return true;
	}

	/**
	 * 初始化Filter
	 */
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		log.debug("init login filter");
		this.encoding = filterConfig.getInitParameter("encoding");
		ServletContext context = filterConfig.getServletContext();
		CONTEXT_PATH = context.getContextPath();
	}
	
	/**
	 * 记录请求前的参数信息
	 * @param request
	 */
	@SuppressWarnings(value={"unchecked"})
	private void preRequestRember(HttpServletRequest request){
		Session session = (Session) request.getSession(true).getAttribute(Session.KEY_NAME);
		if(session == null){
			session = new SessionImpl();
			request.getSession(true).setAttribute(Session.KEY_NAME, session);
		}
		String requestURL = request.getRequestURI();
		requestURL = requestURL.replaceFirst(CONTEXT_PATH, "");
		String method = request.getMethod();
		Map<String, Object> parameter = request.getParameterMap();
		Map<String, Object> paramMap = new HashMap<String, Object>();
		//进行参数拷贝，防止请求结束参数销亡
		copyMap(parameter, paramMap);
		session.setAttribute("returnUrl", requestURL);
		session.setAttribute("returnParameterMap",  paramMap);
		session.setAttribute("returnMethod", method);
	}
	
	/**
	 * 工具方法，后面需要提取到公共的方法类里面
	 * ==============================
	 * 用户Map的拷贝
	 * @param source
	 * @param target
	 */
	private void copyMap(Map<String, Object> source, Map<String, Object> target){
		Set<String> keySet = source.keySet();
		Iterator<String> iterator = keySet.iterator();
		while(iterator.hasNext()){
			String key = iterator.next();
			Object value = (Object) source.get(key);
			target.put(key, value);
		}
		
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		dstMemberInfoService = (IDstMemberInfoService) applicationContext.getBean("dstMemberInfoService");
	}

	
}
